package lumis.portal.controller;

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Method;

import lumis.util.log.ILogger;
import lumis.util.log.LoggerFactory;

/**
 * A print writer that automatically flushes the buffer after writes. But it
 * does not flush the underlying writer.
 *
 * @version $Revision: 12999 $ $Date: 2011-05-18 13:29:49 -0300 (Wed, 18 May 2011) $
 * @since 5.0.0
 */
class AutoFlushBufferPrintWriter extends PrintWriter
{
	private static final ILogger logger = LoggerFactory.getLogger(AutoFlushBufferPrintWriter.class);
	
	private static Method flushBufferMethod;
	static
	{
		try
		{
			flushBufferMethod = OutputStreamWriter.class.getDeclaredMethod("flushBuffer", (Class[])null);
			flushBufferMethod.setAccessible(true);
		}
		catch (Exception e)
		{
			logger.error("Could not obtain access to flushBuffer method.", e);
			flushBufferMethod = null;
		}
	}
	
	private final OutputStreamWriter outputStreamWriter;
	
	public AutoFlushBufferPrintWriter(OutputStreamWriter out)
	{
		super(out);
		this.outputStreamWriter = out;
	}

	private void flushBuffer()
	{
		if (flushBufferMethod != null)
		{
			try
			{
				flushBufferMethod.invoke(outputStreamWriter, (Object[])null);
			}
			catch (Exception e)
			{
				throw new RuntimeException(e);
			}
		}
		else
		{
			// if could not obtain access to flushBuffer, fallback to flush
			flush();
		}
	}

	@Override
	public void write(String s, int off, int len)
	{
		super.write(s, off, len);
		flushBuffer();
	}

	@Override
	public void println()
	{
		super.println();
		flushBuffer();
	}

	@Override
	public void write(char[] buf, int off, int len)
	{
		super.write(buf, off, len);
		flushBuffer();
	}

	@Override
	public void write(int c)
	{
		super.write(c);
		flushBuffer();
	}
}
